import {
    Controller,
    Get,
    Logger,
    NotFoundException,
    Param,
    Post,
    Query,
    Res,
    UploadedFile,
    UseInterceptors,
} from "@nestjs/common";
import { UploadHistoryService } from "../user/service/upload.history.service";
import { FileInterceptor } from "@nestjs/platform-express";
import { Response } from "express";
import { RequsetFileInfoDto } from "src/dto/file";
import { FileService } from "./service/file.service";
import * as fs from "fs-extra";
import { ApiRes, ExcludeTransform, Public, RequsetUser, UsePermGuard, definePermission } from "src/decorator";
import { FolderService } from "./service/folder.service";
import { ApiOperation, ApiTags } from "@nestjs/swagger";
import { UploadHistoryEntity } from "src/entity";
import { FileDownloadInfo, Folder } from "src/common/model";

export const Perm = definePermission("file", {
    upload: {
        name: "上传",
        code: "upload",
        description: "文件上传权限",
    },
    download: {
        name: "下载",
        code: "download",
        description: "文件下载权限",
    },
    folder: {
        name: "浏览",
        code: "folder",
        description: "文件浏览权限",
    }
} as const);



@ApiTags("File - 文件模块")
@Controller("file")
export class FileController {
    private readonly logger = new Logger(FileController.name);

    constructor(
        private readonly uploadHistoryService: UploadHistoryService,
        private readonly fileService: FileService,
        private readonly folderService: FolderService,
    ) {}

    @ApiOperation({ summary: "上传文件" })
    @ApiRes({ type: UploadHistoryEntity })
    @UsePermGuard(Perm.UPLOAD)
    @UseInterceptors(FileInterceptor("file"))
    @Post("upload")
    upload(@RequsetUser("id") id: number, @UploadedFile() file: Express.Multer.File) {
        return this.uploadHistoryService.add(id, { dir: file.destination, filename: file.filename });
    }

    @ApiOperation({ summary: "获取文件下载信息" })
    @ApiRes({ type: FileDownloadInfo })
    @UsePermGuard(Perm.DOWNLOAD)
    @Get("info")
    info(@RequsetUser() user: RequsetUser, @Query() dto: RequsetFileInfoDto) {
        return this.fileService.getFileInfo(user, dto);
    }

    @ApiOperation({ summary: "下载文件" })
    @ExcludeTransform()
    @Public()
    @Get("get/:filename")
    download(
        @Query("type") type: "download" | "playback",
        @Query("token") token: string,
        @Param("filename") filename: string,
        @Res({ passthrough: false }) respone: Response,
    ) {
        const info = this.fileService.verifyToken(token);

        this.logger.log(`download file: token user ${info.userId}, filepath: ${info.filepath}`);

        if (!fs.existsSync(info.filepath)) throw new NotFoundException("文件已不存在!");

        const headers: Record<string, string> = {};

        if (info.mime) headers["Content-Type"] = info.mime;

        const option = {
            headers,
            extensions: false,
            index: false,
        };

        if (type == "download") {
            return respone.download(info.filepath, filename, option, (error) => {
                if (error && error.message != "Request aborted") this.logger.error(error);
            });
        }
        return respone.sendFile(info.filepath, option, (error) => {
            if (error && error.message != "Request aborted") this.logger.error(error);
        });
    }

    @ApiOperation({ summary: "获取文件列表" })
    @ApiRes({ type: Folder })
    @UsePermGuard(Perm.FOLDER)
    @Get("folder")
    folder(@Query("dir") dir: string) {
        return this.folderService.loadCurrentPath(dir);
    }
}
